﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Text;
using Fintech.Utils;
using ZOVNP.Model.Abstracts;

namespace ZOVNP.Engine
{
    /// <summary> Провайдер безопасности для базы Skif. </summary>
    internal class ZOVNPSecurityProvider : IZOVNPSecurityProvider
    {
        #region Поля

        private ZOVNPEngine engine;

        #endregion

        #region Конструкторы

        /// <summary> Создать провайдер безопасности. </summary>
        /// <param name="Engine"> Используемый движок. </param>
        public ZOVNPSecurityProvider(ZOVNPEngine Engine)
        {
            Engine.CheckOnNull("Engine");
            engine = Engine;
        }

        #endregion

        #region Свойства

        /// <summary> Может ли данный движок создавать логины. </summary>
        /// <remarks> Это зависит от прав текущего пользователя. </remarks>
        public bool CanCreateLogin { get { return true; } }

        /// <summary> Может ли данный движок создавать пользователей. </summary>
        /// <remarks> Это зависит от прав текущего пользователя. </remarks>
        public bool CanCreateUser { get { return true; } }
        
        /// <summary> Имеет ли пользователь право удалять пользователей. </summary>
        /// <remarks> Это зависит от прав текущего пользователя. </remarks>
        public bool CanDeleteUser { get { return true; } }

        #endregion

        #region Методы

        /// <summary> Создание нового логина. </summary>
        /// <param name="Login"> Имя логина. </param>
        /// <param name="Password"> Пароль для логина. </param>
        /// <param name="IsSql"> True, если логин является Sql логином, иначе false. </param>
        /// <param name="MustChange"> True, если пользователь должен сменить пароль при первом подключении к системе. </param>
        public bool CreateLogin(string Login, string Password, bool IsSql, bool MustChange)
        {
            engine.GuardDispose();
            if (!CanCreateLogin)
                throw new InvalidOperationException(Properties.Resources.MSG_CreateLoginDisabled);
            long property = 0;
            property = property.SetBit(0, MustChange);
            var paramProvider = engine.ParameterProvider;
            var result = paramProvider.CreateParam("Result", 0, Fintech.Utils.Database.ParameterDirection.ReturnValue);
            engine.ExecuteNonQuery("[access].[p_Create_Login]", CommandType.StoredProcedure,
                paramProvider.CreateParam("LoginName", Login), paramProvider.CreateParam("IsSql", IsSql),
                paramProvider.CreateParam("Password", Password), paramProvider.CreateParam("Property", property), result);
            return (int)result.Value == 0;
        }

        /// <summary> Создание нового пользователя. </summary>
        /// <param name="UserID"> Идентификатор пользователя. </param>
        /// <param name="PrincipalName"> Имя пользователя в БД. </param>
        /// <param name="LoginName"> Логин пользователя на сервере. </param>
        /// <param name="FirstName"> Имя пользователя. </param>
        /// <param name="SecondName"> Отчество пользователя. </param>
        /// <param name="LastName"> Фамилия пользователя. </param>
        /// <param name="Job"> Должность пользователя. </param>
        /// <param name="Room"> Номер комнаты пользователя. </param>
        /// <param name="Phone"> Телефон пользователя. </param>
        /// <param name="EMail"> Адрес электронной почты. </param>
        public bool CreateUser(out Guid UserID, string PrincipalName, string LoginName, string Name, string FirstName = null, string SecondName = null,
            string LastName = null, string Job = null, string Room = null, string Phone = null, string EMail = null)
        {
            engine.GuardDispose();
            if (!CanCreateUser)
                throw new InvalidOperationException(Properties.Resources.MSG_CreateUserDisabled);
            var parameters = new List<DbParameter>();
            UserID = engine.NewGuid();
            var paramProvider = engine.ParameterProvider;
            var result = paramProvider.CreateParam("Result", 0, Fintech.Utils.Database.ParameterDirection.ReturnValue);
            var idParam = paramProvider.CreateParam("ID", UserID);
            parameters.Add(result);
            parameters.Add(idParam);
            parameters.Add(paramProvider.CreateParam("Principal_Name", PrincipalName));
            parameters.Add(paramProvider.CreateParam("Login_Name", LoginName));
            parameters.Add(paramProvider.CreateParam("Name", Name));
            if (FirstName != null) parameters.Add(paramProvider.CreateParam("First_Name", FirstName));
            if (SecondName != null) parameters.Add(paramProvider.CreateParam("Second_Name", SecondName));
            if (LastName != null) parameters.Add(paramProvider.CreateParam("Last_Name", LastName));
            if (Job != null) parameters.Add(paramProvider.CreateParam("Position", Job));
            if (Room != null) parameters.Add(paramProvider.CreateParam("Room_Num", Room));
            if (Phone != null) parameters.Add(paramProvider.CreateParam("Tel", Phone));
            if (EMail != null) parameters.Add(paramProvider.CreateParam("EMail", EMail));
            engine.ExecuteNonQuery("[access].[p_Save_User]", CommandType.StoredProcedure, parameters.ToArray());
            UserID = (Guid)idParam.Value;
            return (int)result.Value == 0;
        }

        /// <summary> Удалить пользователя. </summary>
        /// <param name="UserID"> Идентификатор пользователя. </param>
        /// <returns> </returns>
        public bool DeleteUser(Guid UserID)
        {
            engine.GuardDispose();
            if (!CanDeleteUser)
                throw new InvalidOperationException(Properties.Resources.MSG_DeleteUserDisabled);
            var paramProvider = engine.ParameterProvider;
            var result = paramProvider.CreateParam("Result", 0, Fintech.Utils.Database.ParameterDirection.ReturnValue);
            var idParam = paramProvider.CreateParam("ID", UserID, Fintech.Utils.Database.ParameterDirection.Input);
            engine.ExecuteNonQuery("[access].[p_Drop_User]", CommandType.StoredProcedure, idParam, result);
            return (int)result.Value == 0;
        }

        #endregion
    }
}
